﻿using Basic.FlowCollect;
using Basic.FlowLocalEvent.Model;
using Basic.FlowModel.DB;
using Basic.FlowModel.Node;
using Basic.FlowModel.NodeRoute;
using Basic.FlowRemoteModel.FlowNode.Model;
using Basic.FlowRemoteModel.NodeEvent.Model;
using Basic.FlowService.Interface;
using WeDonekRpc.Client;
using WeDonekRpc.Helper;

namespace Basic.FlowService.lmpl
{
    public class FlowNodeService : IFlowNodeService
    {
        private readonly IFlowNodeCollect _Service;
        private readonly IFlowCollect _Flow;
        private readonly INodeRouteCollect _Route;
        private readonly INodeEventCollect _NodeEvent;
        private readonly INodeAuditEmpCollect _AuditEmp;
        public FlowNodeService ( IFlowNodeCollect service,
            INodeRouteCollect route,
            INodeEventCollect nodeEvent,
            INodeAuditEmpCollect auditEmp,
            IFlowCollect flow )
        {
            this._AuditEmp = auditEmp;
            this._NodeEvent = nodeEvent;
            this._Service = service;
            this._Route = route;
            this._Flow = flow;
        }

        public long Add ( FlowNodeAdd data )
        {
            if ( !data.FormId.HasValue )
            {
                data.FormId = this._Flow.GetDefFormId(data.FlowId);
            }
            return this._Service.Add(data);
        }
        public bool SetForm ( long id, FlowNodeForm set )
        {
            DBFlowNode sour = this._Service.Get(id);
            if ( this._Service.SetForm(sour, set) )
            {
                new FlowNodeEvent(sour).AsyncSend("Update");
                return true;
            }
            return false;
        }
        public bool Set ( long id, FlowNodeSet set )
        {
            if ( set.LimitTime.HasValue && set.LimitTime.Value == 0 )
            {
                set.LimitTime = null;
            }
            if ( set.MinAuditPass.HasValue && set.MinAuditPass.Value == 0 )
            {
                set.MinAuditPass = null;
            }
            if ( set.BackNodeId.HasValue && set.BackNodeId.Value == 0 )
            {
                set.BackNodeId = null;
            }
            DBFlowNode sour = this._Service.Get(id);
            if ( this._Service.Set(sour, set) )
            {
                new FlowNodeEvent(sour).AsyncSend("Update");
                return true;
            }
            return false;
        }
        public void Delete ( long id )
        {
            DBFlowNode sour = this._Service.Get(id);
            this._Service.Delete(sour);
            new FlowNodeEvent(sour).AsyncSend("Delete");
        }
        public FlowNodeDto Get ( long id )
        {
            DBFlowNode sour = this._Service.Get(id);
            FlowNodeDto dto = sour.ConvertMap<DBFlowNode, FlowNodeDto>();
            dto.NodeEvent = this._NodeEvent.GetsByNode<NodeEventDto>(id).ToDictionary(a => (int)a.EventType, a => a.EventId);
            FromToNode[] nid = this._Route.GetsFromToNode(id);
            if ( !nid.IsNull() )
            {
                long[] ids = nid.Convert(c => c.ToNodeId == id, c => c.NodeId);
                if ( ids.Length > 0 )
                {
                    dto.FromNode = this._Service.Gets<BaseNode>(ids);
                }
                ids = nid.Convert(c => c.NodeId == id, c => c.ToNodeId);
                if ( ids.Length > 0 )
                {
                    dto.ToNode = this._Service.Gets<BaseNode>(ids);
                }
            }
            return dto;
        }
        public FlowNodeBase[] GetNodes ( long flowId )
        {
            NodeBase[] list = this._Service.Gets<NodeBase>(flowId);
            if ( list.IsNull() )
            {
                return Array.Empty<FlowNodeBase>();
            }
            FlowNodeBase[] nodes = list.ConvertMap<NodeBase, FlowNodeBase>();
            RouteBase[] routes = this._Route.Gets<RouteBase>(flowId);
            Dictionary<long, string> show = this._AuditEmp.GetShow(flowId);
            nodes.ForEach(c =>
            {
                c.Show = show.GetValueOrDefault(c.Id);
                if ( !routes.IsNull() )
                {
                    c.ToNode = routes.Convert(a => a.NodeId == c.Id, a => new FlowToNode
                    {
                        NodeId = a.ToNodeId,
                        Id = a.Id,
                    });
                }
            });
            return nodes;
        }
        public bool SetBeginNode ( long id, BeginNodeSet node )
        {
            DBFlowNode sour = this._Service.Get(id);
            return this._Service.Set(sour, node);
        }
        public void SetCoordinate ( long id, ImgPoint point )
        {
            DBFlowNode sour = this._Service.Get(id);
            this._Service.SetCoordinate(sour, point);
        }

        public bool SetIntoOut ( long id, FlowNodeIntoOut datum )
        {
            DBFlowNode sour = this._Service.Get(id);
            return this._Service.SetIntoOut(sour, datum);
        }
    }
}
